const uuid = require('uuid');
const path = require('path');
const AWS = require('aws-sdk');
const multiparty = require('multiparty');
const loopback = require('loopback');
const connector = require('loopback-component-storage');
const soag = require('lilly-soag');

module.exports = function getUploadService(req) {
  let uploadService;
  if (process.env.AWS_S3_IS_USED === 'true') {
    uploadService = getAWSService(req);
  } else {
    uploadService = req.app.models.Upload;
  }
  return Promise.resolve(uploadService);
};

function getAWSService(req) {
  const { aws } = req.session;
  if (aws && req.session.expired_date > new Date().getTime()) {
    return Promise.resolve(new AWSService(aws));
  }
  return soag.getAWSCredential(req.session)
    .then((response) => {
      const { AccessKeyId, SecretAccessKey, SessionToken, Expiration } = response.data.AssumeRoleWithSAMLResponse.AssumeRoleWithSAMLResult.Credentials;
      const aws = {
        accessKeyId: AccessKeyId,
        secretAccessKey: SecretAccessKey,
        sessionToken: SessionToken,
        expiration: Expiration,
      };
      req.session.aws = aws;
      return Promise.resolve(new AWSService(aws));
    });
}

class AWSService {
  constructor(options) {
    const {
      secretAccessKey,
      accessKeyId,
      sessionToken,
    } = options;

    this.s3 = new AWS.S3({
      accessKeyId,
      secretAccessKey,
      sessionToken,
    });
  }

  download(req, res, container, file, cb) {
    try {
      const params = {
        Bucket: container,
        Key: file,
      };
      this.s3.getObject(params, (err, data) => {
        if (err) {
          cb(err);
          return;
        }
        
        cb(null, data);

      });
    } catch (error) {
      cb(error);
    }
  }

  upload(req, res, options, cb) {
      try {
          console.log(`Start AWS upload`);
      const form = new multiparty.Form();
      const result = { files: {} };
      let count = 0;
      form.on('part', (part) => {
        if (part.filename) {
          const { filename, name, byteCount } = part;
          const contentType = part.headers['content-type'];
          count += 1;
          const key = path.join(options.prefix, uuid.v4() + path.extname(filename).toLowerCase());
          const params = {
            Bucket: options.container,
            Key: key,
            Body: part,
            ContentLength: byteCount,
            ContentType: contentType || null,
            ServerSideEncryption: 'aws:kms',
            Metadata: {
              'original-filename': encodeURIComponent(filename),
            }
          };

          try {
            this.s3
              .upload(params)
              .send((err, data) => { // eslint-disable-line
                if (err) {
                  cb(err);
                  return;
                }
                if (!result.files[name]) {
                  result.files[name] = [];
                }
                result.files[name].push({
                  container: options.container,
                  name: key,
                  originalFilename: filename,
                  size: byteCount,
                });
  
                count -= 1;
                if (count === 0) {
                  cb(null, result);
                }
              });
          } catch (error) {
            cb(error);
          }

          part.on('error', (err) => {
            cb(err);
          });
        } else {
          part.resume();
        }
      });

      form.on('close', () => {
        if (count === 0) {
          cb(new Error('Cannot find the upload file.'));
        }
      });

      form.parse(req);
    } catch (error) {
      cb(error);
    }
  }
}

function awsService(credential) {
  const { secretAccessKey, accessKeyId, sessionToken } = credential;
  if (!secretAccessKey || !secretAccessKey) {
    return null;
  }

  return loopback.createDataSource({
    connector,
    provider: 'amazon',
    key: secretAccessKey,
    keyId: accessKeyId,
    token: sessionToken,
    maxFileSize: 10485760,
    allowedContentTypes: [
      'image/png',
      'image/jpeg',
      'application/pdf',
      'application/msword',
      'application/vnd.ms-excel',
      'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
    ],
  });
}
